/*******************************************************************************
 * Copyright (c) 2014 Joel Thurlby.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Joel Thurlby - initial API and implementation
 ******************************************************************************/
package jat.xtext.gantt.ui.diagram;

import jat.xtext.gantt.ganttText.Task;
import jat.xtext.gantt.ganttText.WorkPackage;
import jat.xtext.gantt.validation.GanttTextValidator;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.xtext.resource.EObjectAtOffsetHelper;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.XtextEditor;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import org.eclipse.xtext.util.concurrent.IUnitOfWork;

public class GanttEditorListener implements IPartListener2, ISelectionChangedListener {
	private final String JAT_XTEXT_GANTT_GANTTTEXT = "jat.xtext.gantt.GanttText";

	private GanttChartViewer m_viewer = null;
	private XtextEditor m_currentEditor = null;

	public GanttEditorListener(GanttChartViewer viewer) {
		m_viewer = viewer;
	}

	@Override
	public void partActivated(IWorkbenchPartReference partRef) {
		if (JAT_XTEXT_GANTT_GANTTTEXT.equals(partRef.getId())) {
			XtextEditor editor = (XtextEditor) partRef.getPage().getActiveEditor();
			editor.getSelectionProvider().addSelectionChangedListener(this);
			IXtextDocument document = editor.getDocument();
			GanttTextValidator.setActiveDocument(document);
			document.addModelListener(m_viewer);
		}
	}

	@Override
	public void partBroughtToTop(IWorkbenchPartReference partRef) {

	}

	@Override
	public void partClosed(IWorkbenchPartReference partRef) {
		if (JAT_XTEXT_GANTT_GANTTTEXT.equals(partRef.getId())) {
			m_viewer.clearChart();
		}
	}

	@Override
	public void partDeactivated(IWorkbenchPartReference partRef) {
		if (JAT_XTEXT_GANTT_GANTTTEXT.equals(partRef.getId())) {
			XtextEditor editor = (XtextEditor) partRef.getPage().getActiveEditor();
			IXtextDocument document = editor.getDocument();
			if (document != null) {
				document.removeModelListener(m_viewer);
			}
		}
	}

	@Override
	public void partOpened(IWorkbenchPartReference partRef) {
		if (JAT_XTEXT_GANTT_GANTTTEXT.equals(partRef.getId())) {
			XtextEditor editor = (XtextEditor) partRef.getPage().getActiveEditor();
			// Only reload the document when the editor changes.
			if (m_currentEditor != editor) {
				m_currentEditor = editor;
				m_viewer.loadModel(editor.getDocument());
			}
		}
	}

	@Override
	public void partHidden(IWorkbenchPartReference partRef) {

	}

	@Override
	public void partVisible(IWorkbenchPartReference partRef) {
		partOpened(partRef);
	}

	@Override
	public void partInputChanged(IWorkbenchPartReference partRef) {

	}

	@Override
	public void selectionChanged(final SelectionChangedEvent event) {
		if (m_currentEditor == null)
			return;

		if (event.getSelection() instanceof TextSelection) {
			m_currentEditor.getDocument().readOnly(new IUnitOfWork.Void<XtextResource>() {
				@Override
				public void process(XtextResource state) throws Exception {
					final TextSelection sel = (TextSelection) event.getSelection();
					final int offset = sel.getOffset();
					EObjectAtOffsetHelper helper = new EObjectAtOffsetHelper();
					EObject obj = helper.resolveContainedElementAt(state, offset);
					if (obj instanceof Task) {
						Task task = (Task) obj;
						m_viewer.taskSelected(task);
					} else if (obj instanceof WorkPackage) {
						WorkPackage workPackage = (WorkPackage) obj;
						m_viewer.workPackageSelected(workPackage);
					}
				}
			});
		}
	}
}
